/*!
 * \file grinput.c
 *
 * \date Sep 28, 2013
 * \author Ricardo C. Corrêa (correa@lia.ufc.br)
 *
 * \brief A function to read a graph from a file in the DIMACS format.
 */

#include <stdio.h>
#include <string.h>
#include <graph.h>

static void getGraphSize(FILE* graphFile, size_t * n, size_t * m) {
	char type = ' ';
	char linestr[100];
	char* datastr;
	*n = 0;
	*m = 0;

	while (type != 'p') {
		type = fgetc(graphFile);
		if (type != EOF) {

			/* header */
			if (type == 'c') {
				datastr = fgets(linestr, 100, graphFile);
				if (datastr != NULL)
					printf("%s", linestr);
				else {
					*n = -1;
					return;
				}
			}

			/* Vertices */
			if (type == 'p') {
				datastr = fgets(linestr, 100, graphFile);
				if (datastr == NULL) {
					*n = -1;
					return;
				}
				datastr = strtok(linestr, " ");
				printf("\tdatastr:%s\n", datastr);
				if (!strcmp(datastr, "edge") || !strcmp(datastr, "col")) {
					datastr = strtok(NULL, " ");
					printf("\tdatastr:%s\n", datastr);
				}
				*n = atoi(datastr);

				datastr = strtok(NULL, " ");
				printf("\tdatastr:%s\n", datastr);
				*m = atoll(datastr);

				printf("Graph with (%d) vertices and (%d) edges.\n", *n, *m);
				printf("Density: %3.2f\n", 2.0 * ((double) *m) / (*n * (*n)));
			}
		}
	}
}

/*!
 * \fn Graph * readDimacsGraph(FILE* graphFile)
 * \brief Reads a graph from a specified file in the DIMACS format.
 *
 * A new graph is created.
 *
 * \param graphFile The input file in the DIMACS format.
 *
 * \return The graph read from the specified file.
 */
Graph * readDimacsGraph(FILE* graphFile) {
	char type = ' ';
	char linestr[100];
	char* datastr;
	int i, j;
	size_t n;
	size_t m;

	printf("\t#Starts reading...\n");
	getGraphSize(graphFile, &n, &m);

	////
	// Graph variables
	////
	Graph * g = newGraph(n);
	g->m = m;

	type = fgetc(graphFile);
	while (type != EOF) {
		/* Edges */
		if (type == 'e') {
			datastr = fgets(linestr, 100, graphFile);
			if (datastr == NULL)
				return 0;

			datastr = strtok(linestr, " ");
			i = atoi(datastr) - 1;

			datastr = strtok(NULL, " ");
			j = atoi(datastr) - 1;

//			printf("i=%d  j=%d\n",i,j);
//			fflush(NULL);
			addEdge(g, i, j);
		} else {
			datastr = fgets(linestr, 100, graphFile);
			if (datastr != NULL)
				printf(" %s\n", linestr);
			else
				return NULL;
		}
		type = fgetc(graphFile);
	}
	printf("\t#Finishes reading graph\n");

	return g;
}

/*!
 * \fn readDoubleWeights(size_t n, FILE* weightsFile)
 * \brief Read and return an array of double weights from a specified file
 *
 * A new array is allocated to store the weights.
 *
 * File format:
 *
 *       c random-1.clq
 *       c
 *       c Created on: Jan 20, 2011
 *       c     Author: correa
 *       c
 *       c 4096 values
 *       c
 *       w 0.0246
 *
 *
 * \param n the number of weights to read
 * \param weightsFile the file containing the weights
 */
double * readDoubleWeights(size_t n, FILE* weightsFile) {
	char type = ' ';
	char linestr[100];
	char* datastr;
	int i;

	double * w;
	w = calloc(n, sizeof(double));

	i = 0;
	type = fgetc(weightsFile);
	while (i < n && type != EOF) {
		/* Edges */
		if (type == 'w') {
			datastr = fgets(linestr, 100, weightsFile);
			if (datastr == NULL)
				return 0;

			datastr = strtok(linestr, " ");
			w[i++] = atof(datastr);
		} else {
			datastr = fgets(linestr, 100, weightsFile);
			if (datastr != NULL)
				printf(" %s\n", linestr);
			else
				return NULL;
		}
		type = fgetc(weightsFile);
	}
	printf("\t#Finishes reading weights\n");

	return w;
}

/*!
 * \fn readIntWeights(size_t n, FILE* weightsFile)
 * \brief Read and return an array of integer weights from a specified file
 *
 * A new array is allocated to store the weights.
 *
 * File format:
 *
 *       c random-1.clq
 *       c
 *       c Created on: Jan 20, 2011
 *       c     Author: correa
 *       c
 *       c 4096 values
 *       c
 *       w 0.0246
 *
 *
 * \param n the number of weights to read
 * \param weightsFile the file containing the weights
 */
double * readIntWeights(size_t n, FILE* weightsFile) {
	char type = ' ';
	char linestr[100];
	char* datastr;
	int i;

	double * w;
	w = calloc(n, sizeof(double));

	i = 0;
	type = fgetc(weightsFile);
	while (i < n && type != EOF) {
		/* Edges */
		if (type == 'w') {
			datastr = fgets(linestr, 100, weightsFile);
			if (datastr == NULL)
				return 0;

			datastr = strtok(linestr, " ");
			w[i++] = (int) (10 * atof(datastr));
		} else {
			datastr = fgets(linestr, 100, weightsFile);
			if (datastr != NULL)
				printf(" %s\n", linestr);
			else
				return NULL;
		}
		type = fgetc(weightsFile);
	}
	printf("\t#Finishes reading weights\n");

	return w;
}
